2005年07月07日
川俣晶の縁側ソフトウェア技術雑記 total 13309 count

C系言語で、a = b = 123;といった複数対象への値の代入を積極的に肯定すべきか?

Written By: 川俣 晶連絡先

 C系の言語では、代入のイコール(=)は演算子です。

 一方、BASICやPascalの代入のイコール(=)は、代入構文の一部で演算子ではありません。(Pascalの場合は=ではなく、:=ですが)

 最初にCに触れた時はこの相違があまりに意外で面食らいました。

 何しろ、条件判断しながら代入もしてしまうif( a=0 )のような記述が可能なのですから。

しかし…… §

 それはトラブルの元になることが多く、1つの文が複数の機能を持つような紛らわしい機能は良くないだろうと思っていました。

 確かに上記のような例は好ましくないものの、代入のイコール(=)は演算子の方が良いのではないか、と思える事例に出会いました。

 (まあ、良いことがあるからこそ、このような仕様がCの子供達……C++, Java, C#にも継承されているのでしょうが)

これが経緯だ! §

 ついさっき、C#で2つのプロパティに同じ値を設定するコードを書くことになったのですが、これをスマートに重複無くシンプルに書き切る方法を探していました。

 何も考えないと以下のような感じに書かれることになります。

a.prop1 = ちょっと負担の重い式;

a.prop2 = ちょっと負担の重い式;

 しかし、同じ式が2回も出てきて、しかもそれの負担が重いのは面白くありません。

 以下のように書き換える方法が最初に思い浮かびます。

v = ちょっと負担の重い式;

a.prop1 = v;

a.prop2 = v;

 しかし、ローカル変数を好ましくない存在と見なして追放したいリファクタリングの考え方からすれば、vは使いたくありません。

 これを使わないとすれば、以下のように書き直せます。

a.prop1 = ちょっと負担の重い式;

a.prop2 = a.prop1;

 prop1が、読み書きに透過的なプロパティならこれで動作します。

 しかし、ソースの明瞭さという意味では肯定できません。

 このソースから、2つのプロパティに式の設定するという意図はすっきりと読み取れません。ここから素直に読み取れるのは、prop1への値の設定と、prop1からprop2への値のコピーという2つの動作だけです。本来の意図を理解するには、この2行を関連付けて解釈しなければなりません。

 さて、この欠陥を解決する最もスマートなコードは何かと考えた時、かつて一度は否定した以下のコードが最善であると気付いたわけです。

a.prop1 = a.prop2 = ちょっと負担の重い式;

 これなら、式の値を2つのプロパティに代入するという意図を明瞭に示すことができます。

 このような構文が可能になることは有益であり、代入のイコールが演算子である価値があると実感しました。